package com.jddup.program.comparator.impl;

import com.jddup.common.pojo.EntityAndDbDifference;
import com.jddup.common.pojo.TableColumn;
import com.jddup.common.pojo.TableMeta;
import com.jddup.program.comparator.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.stream.Collectors;

/**
 * Created by zhangzhenbin on 17-12-11.
 */
public class EntityAndDbComparatorImpl implements EntityAndDbComparator {
    private static final Logger logger = LoggerFactory.getLogger(EntityAndDbComparatorImpl.class);
    private AddPkDDLBuilder addPkDDLBuilder;
    private AddColumnDDLBuilder addColumnDDLBuilder;
    private DropDDLBuilder dropDDLBuilder;
    private CreateDDLBuilder createDDLBuilder;
    private DataTypeCompatibility dataTypeCompatibility;

    public EntityAndDbComparatorImpl(AddPkDDLBuilder addPkDDLBuilder, AddColumnDDLBuilder addColumnDDLBuilder,
                                     DropDDLBuilder dropDDLBuilder,
                                     CreateDDLBuilder createDDLBuilder, DataTypeCompatibility dataTypeCompatibility) {
        this.addPkDDLBuilder = addPkDDLBuilder;
        this.addColumnDDLBuilder = addColumnDDLBuilder;
        this.dropDDLBuilder = dropDDLBuilder;
        this.createDDLBuilder = createDDLBuilder;
        this.dataTypeCompatibility = dataTypeCompatibility;
    }

    @Override
    public EntityAndDbDifference comparator(TableMeta entity, TableMeta db) {
        EntityAndDbDifference entityAndDbDifference = new EntityAndDbDifference(entity.getTableName(), entity.getBeanName());
        String createTableDdl = createDDLBuilder.build(entity);
        entityAndDbDifference.setCreateTableDdl(createTableDdl);
        if (db == null) {
            entityAndDbDifference.setTableExist(false);
            putIntoDifference(entityAndDbDifference,"&table", "数据库不存在！请执行SQL语句",EntityAndDbDifference.ModifyDDL.LevelEnums.serious, createTableDdl);
        } else {
            entityAndDbDifference.setTableExist(db.getTableExist());
            if(db.getTableExist()) {
                //1 检查主键
                TableColumn entityPk = entity.getPrimaryKeyColumn();
                TableColumn dbPk = db.getPrimaryKeyColumn();
                if (entityPk == null && dbPk != null) {
                    putIntoDifference(entityAndDbDifference, "&table", "实体主键未加@Id注解！请在实体中添加@Id注解。", EntityAndDbDifference.ModifyDDL.LevelEnums.serious);
                }
                if (dbPk == null && entityPk != null) {
                    putIntoDifference(entityAndDbDifference, "&table", "数据库中未设置主键！请执行SQL完成创建主键！", EntityAndDbDifference.ModifyDDL.LevelEnums.serious, addPkDDLBuilder.build(entity, entityPk));
                }
                if (entityPk != null && dbPk != null && !entityPk.getColumnName().equals(dbPk.getColumnName())) {
                    putIntoDifference(entityAndDbDifference, "&table", "数据库和实体主键不一致！请修改实体中@Id注解或执行以下SQL！",
                            EntityAndDbDifference.ModifyDDL.LevelEnums.serious,
                            addPkDDLBuilder.removeOld(db, dbPk.getColumnName()), addPkDDLBuilder.build(entity, entityPk));
                }

                //2 检查各字段
                Map<String, TableColumn> entityColumnMap = entity.getTableColumns().stream().collect(Collectors.toMap(o -> o.getColumnName().toLowerCase(), o -> o));
                Map<String, TableColumn> dbColumnMap = db.getTableColumns().stream().collect(Collectors.toMap(o -> o.getColumnName().toLowerCase(), o -> o));
                //2.1 检查entity中有，但是db中没有的
                entityColumnMap.forEach((s, tableColumn) -> {
                    if (!dbColumnMap.containsKey(s)) {
                        putIntoDifference(entityAndDbDifference, s, "数据库中[" + s + "]字段不存在！请修改实体字段或者执行以下SQL！",
                                EntityAndDbDifference.ModifyDDL.LevelEnums.serious, addColumnDDLBuilder.build(entity, tableColumn));

                    } else {
                        dataTypeCompatibility.compare(entityAndDbDifference, tableColumn, dbColumnMap.get(s));
                    }
                });
                //2.2 检查entity中没有有，但是Db中有的
                dbColumnMap.forEach((s, tableColumn) -> {
                    if (!entityColumnMap.containsKey(s)) {
                        putIntoDifference(entityAndDbDifference, s, "实体中[" + s + "]字段不存在！请修改实体或者删除数据库中对应字段(谨慎操作)！",
                                EntityAndDbDifference.ModifyDDL.LevelEnums.serious, dropDDLBuilder.build(entity, tableColumn));

                    }
                });
            }
        }
        return entityAndDbDifference;

    }
}
